home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
exampleCode
/
opengl
/
xlib
/
zrgb_pup.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-11
|
17KB
|
543 lines
/*
* Copyright (c) 1994, Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the name of Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
* POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
/*
* zrgbmenu.c:
*
* OpenGL-Xlib doublebuffered-RGB, depth-buffering, pop-up menu examp
*
* zrgbmenu is the openGL "after" version of the IrisGL
* "before" program, ~4Dgifts/examples/grafix/zrgbmenu.c
*
* It further implements--either manually via LEFTMOUSE, or in an
* "automatic" (i.e. animation) mode format--movement of the polygons
* via compound rotations to allow for continuous screen-oriented
* rotations (see orient(), spin(), and drawScene() below). Horizontal
* mouse movement rotates the polygons about the y-axis where right is
* positive and left is negative. Vertical mouse movement rotates the
* polygons about the x-axis where down is positive and up is negative.
*
* ratman - 1989
* 1994, ported to OpenGL
*/
#include <GL/glx.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include "pup.h"
#define TRUE 1
#define FALSE 0
/* Modes the program can be in */
#define NOTHING 0
#define ORIENT 1
#define SPIN 2
/* Values returned from popup menu */
#define MANUAL 1
#define AUTOMATIC 2
#define EXIT 3
Display *dpy; /* The X server connection */
Atom del_atom; /* WM_DELETE_WINDOW atom */
Window glwin; /* handle to the GL window */
XEvent event;
/* function declarations */
static void openwindow(char *);
static void resize_buffer(void);
static void clean_exit(void);
void initGL(void);
void orient(void);
void update_scene(void);
void spin(void);
void drawScene(void);
void drawPolys(void);
static float objmat[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
};
int xsize, ysize; /* current size-of-window keepers */
long buffermode; /* flag tracks current window (single or double) */
int xpos, ypos, oxpos, oypos; /* old and new mouse position */
int mode = 0;
int menu;
int omx, mx, omy, my; /* old and new mouse position */
float scrnaspect; /* aspect ratio value */
main(argc, argv)
int argc;
char *argv[];
{
int myExpose, myConfigure, myButtPress, myKeyPress;
int needToDraw = 0; /* don't set this to true until
we get our first Expose event */
long menuval;
myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
openwindow(argv[0]);
initGL(); /* do GL init stuff */
/*
* The event loop.
*/
while (1) { /* standard logic: get event(s), process event(s) */
XEvent event;
KeySym keysym;
char buf[4];
/* this "do while" loop does the `get events' half of the "get events,
* process events" action of the infinite while. this is to ensure
* the event queue is always drained before the events that have come
* in are processed.
*/
while (XPending(dpy)) {
XNextEvent(dpy, &event);
switch (event.type) {
/* "Expose" events are sort of like "REDRAW" in gl-speak in
* terms of when a window becomes visible, or a previously
* invisible part becomes visible.
*/
case Expose: /* Exposures */
needToDraw = myExpose = TRUE;
break;
/* "ConfigNotify" events are like "REDRAW" in terms of changes
* to a window's size or position.
*/
case ConfigureNotify: /* Resize GL manually */
xsize = event.xconfigure.width;
ysize = event.xconfigure.height;
needToDraw = myConfigure = TRUE;
break;
/* Wait for "MotionNotify" events so the queue doesn't fill up
*/
case MotionNotify:
myButtPress = TRUE;
xpos = event.xmotion.x;
ypos = event.xmotion.y;
if (mode == ORIENT) {
update_scene();
needToDraw=TRUE;
}
mode = ORIENT;
break;
/* "ButtonPress" events hail from the ButtonPressMask feed to
* XCreateWindow via XSetWindowAttributes' event_mask field
*/
case ButtonPress:
if (event.xbutton.button == Button3) { /* RIGHTMOUSE: */
menuval = dopup(menu);
switch(menuval) {
case MANUAL:
mode = NOTHING;
break;
case AUTOMATIC:
mode = SPIN;
needToDraw = TRUE;
break;
case EXIT:
clean_exit();
break;
default:
break;
}
}
/* Wait for "ButtonRelease" events so the queue doesn't fill up
* the way it wud if the user sits on ButtonPresss.
*/
case ButtonRelease:
if (event.xbutton.button == Button1) /* LEFTMOUSE: */
mode = NOTHING; /* switch back to */
break; /* "manual" mode */
/* "ClientMessage" is generated if the WM itself is being
* gunned down and sends an exit signal to any running prog.
*/
case ClientMessage:
if (event.xclient.data.l[0] == del_atom)
clean_exit();
break;
/* "KeyPress" events are those that would be generated before
* whenever queueing up any KEYBD key via qdevice.
*/
case KeyPress:
/* save out which unmodified key (i.e. the key was
* not modified w/something like "Shift", "Ctrl",
* or "Alt") got pressed for use below.
*/
XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
myKeyPress = TRUE;
break;
default:
break;
} /* end switch (event.type) */
}
/* On an "Expose" event, redraw the affected pop'd or de-iconized window
*/
if (myExpose) {
resize_buffer();
myExpose = FALSE; /* reset flag--queue now empty */
}
/* On a "ConfigureNotify" event, the GL window has either been moved or
* resized. Respond accordingly and then redraw its contents.
*/
if (myConfigure) {
oxpos = xpos;
oypos = ypos;
resize_buffer();
myConfigure = FALSE; /* reset flag--queue now empty */
}
if (needToDraw) {
if (mode == SPIN) {
update_scene();
drawScene();
/*
* Note: Don't reset needToDraw, so we keep on
* spinning.
*/
} else {
drawScene();
needToDraw = FALSE;
}
}
/* On a keypress of Esc key, exit program.
*/
if (myKeyPress) {
if (keysym == XK_Escape)
clean_exit();
}
if (myButtPress) {
orient();
drawScene();
myButtPress = FALSE;
/*
mode = NOTHING;
*/
}
} /* end while(1) */
} /* end main */
static int attributeList[] = { GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None };
static int attributeList2[] = { GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None };
static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
}
/* openwindow -
* establish connection to X server, get screen info, specify the
* attributes we want the WM to try to provide, and create the GL window
*/
static void openwindow(char *progname) {
XVisualInfo *vi;
GLXContext cx;
Colormap cmap;
XSizeHints Winhints; /* used to fix window size */
XSetWindowAttributes swa;
int scrnnum; /* X screen number */
int xorig, yorig; /* window (upper-left) origin */
long scrnwidth, scrnheight;
/* define window initial size */
xorig = 50; yorig = 40;
xsize = 300; ysize = 240;
/* Connect to the X server and get screen info */
if ((dpy = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "%s: cannot connect to X server %s\n",
progname, XDisplayName(NULL));
exit(1);
}
scrnnum = DefaultScreen(dpy);
scrnwidth = DisplayWidth(dpy, scrnnum);
scrnheight = DisplayHeight(dpy, scrnnum);
/* Code to keep same aspec ratio as the screen */
scrnaspect = ((float)scrnwidth)/((float)scrnheight);
/* get an appropriate visual */
vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
if (vi == NULL) {
fprintf(stderr, "Unable to obtain Doublebuffered visual; ");
fprintf(stderr, "now going for singlebuffer'd...\n");
vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
}
if (vi == NULL) {
printf("Unable to obtain Singlebuffered VISUAL(????)\n");
exit(0);
}
/* create GLX context */
cx = glXCreateContext(dpy, vi, None, GL_TRUE);
/* create a colormap */
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
vi->visual, AllocNone);
/* create a window */
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask
| ExposureMask | Button1MotionMask | KeyPressMask;
glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
xorig, yorig, xsize, ysize,
0, vi->depth, InputOutput, vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);
XMapWindow(dpy, glwin);
XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
/* connect the context to the window */
glXMakeCurrent(dpy, glwin, cx);
if (!(glwin)) {
fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
exit(1);
}
/* define string that will show up in the window title bar (and icon) */
XStoreName(dpy, glwin, "rgb depth/dbl -buffered pop-up menu prog");
/* specify the values for the Window Size Hints we want to enforce: this
* window's aspect ratio needs to stay at 1:1, constrain min and max
* window size, and specify the initial size of the window.
*/
Winhints.width = xsize; /* specify desired x/y size of window */
Winhints.height = ysize;
Winhints.min_width = xorig; /* define min and max */
Winhints.max_width = scrnheight-1; /* width and height */
Winhints.min_height = yorig;
Winhints.max_height = scrnheight-1;
Winhints.min_aspect.x = scrnwidth;/* keep aspect to a scrnX:scrnY ratio */
Winhints.max_aspect.x = scrnwidth;
Winhints.min_aspect.y = scrnheight;
Winhints.max_aspect.y = scrnheight;
Winhints.flags = USSize|PMaxSize|PMinSize|PAspect; /* set the */
XSetNormalHints(dpy, glwin, &Winhints); /* corresponding flags */
/* express interest in WM killing this app */
if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
XSetWMProtocols(dpy, glwin, &del_atom, 1);
menu = defpup(dpy, scrnnum,
"OGL RGB depth-bufr'd pup prog %t|Manual Mode|Automatic Mode|Exit");
return ;
}
/* window has been moved or resized so update viewport & CTM stuff.
*/
static void resize_buffer() {
scrnaspect = xsize / (double) ysize;
glViewport(0, 0, xsize-1, ysize-1);
}
/* clean up before exiting
*/
static void clean_exit(void)
{
XCloseDisplay(dpy);
exit(0);
}
/* setup all necessary GL initialzation parameters.
*/
void initGL(void)
{
glEnable(GL_DEPTH_TEST);
glClearColor(0.16, 0.39, 0.78, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluPerspective(400.0, scrnaspect, 30.0, 600.0);
}
void update_scene(void) {
switch (mode) {
case ORIENT:
orient();
break;
case SPIN:
spin();
break;
}
}
void orient(void)
{
float dx, dy;
glPushMatrix();
dx = 0.01 * (xpos-oxpos);
dy = 0.01 * (oypos-ypos);
glLoadIdentity();
glRotatef(dx, 1.0, 0.0, 0.0);
glRotatef(dy, 0.0, 1.0, 0.0);
glMultMatrixf(objmat);
glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
glPopMatrix();
}
void spin (void) {
glPushMatrix();
glLoadIdentity();
glRotatef(2.5, 1.0, 0.0, 0.0);
glRotatef(3.0, 0.0, 1.0, 0.0);
glRotatef(2.0, 0.0, 0.0, 1.0);
glMultMatrixf(objmat);
glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
glPopMatrix();
}
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluPerspective(400.0, scrnaspect, 30.0, 600.0);
glTranslatef(0.0, 0.0, -40.0);
glMultMatrixf(objmat);
glRotatef(-400.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
drawPolys();
glXSwapBuffers(dpy, glwin);
}
float polygon1[3][3] = { {-10.0, -10.0, 0.0,},
{ 10.0, -10.0, 0.0,},
{-10.0, 10.0, 0.0,} };
float polygon2[3][3] = { { 0.0, -10.0, -10.0,},
{ 0.0, -10.0, 10.0,},
{ 0.0, 5.0, -10.0,} };
float polygon3[4][3] = { {-10.0, 6.0, 4.0,},
{-10.0, 3.0, 4.0,},
{ 4.0, -9.0, -10.0,},
{ 4.0, -6.0, -10.0,} };
void drawPolys(void) {
glBegin(GL_POLYGON);
glColor4f(0.0, 0.0, 0.0, 0.0);
glVertex3fv(&polygon1[0][0]);
glColor4f(0.5, 0.5, 0.5, 0.0);
glVertex3fv(&polygon1[1][0]);
glColor4f(1.0, 1.0, 1.0, 0.0);
glVertex3fv(&polygon1[2][0]);
glEnd();
glBegin(GL_POLYGON);
glColor4f(1.0, 1.0, 0.0, 0.0);
glVertex3fv(&polygon2[0][0]);
glColor4f(0.0, 1.0, 0.5, 0.0);
glVertex3fv(&polygon2[1][0]);
glColor4f(0.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon2[2][0]);
glEnd();
glBegin(GL_POLYGON);
glColor4f(1.0, 1.0, 0.0, 0.0);
glVertex3fv(&polygon3[0][0]);
glColor4f(1.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[1][0]);
glColor4f(0.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[2][0]);
glColor4f(1.0, 0.0, 1.0, 0.0);
glVertex3fv(&polygon3[3][0]);
glEnd();
}